/*******************************************/
// FAT.c
// ee_hqxaa, Hilda
// in this file, we make use of functions from SD.c
// to access FAT32 system to find and load the file
/*******************************************/
// with reference to http://www.icdev.com.cn/?viewthread-6823.html
// with reference to Zhang Qi Bo
// with reference to MicroSoft Extensive Firmware Initiative FAT32 File System Specification
/*******************************************/
// cluster number + x = (LBA + 1)
// x = #hidden sectors + #FATs * sectorsPerFAT + secsPerFDT - 2
// we can use cluster number to get CHS
//******************************************
// 0 sector structure:  446 bytes BS (including BPB) + 64 bytes DPT + 2 bytes signature
// with reference to http://cache.baidu.com/c?m=9d78d513d99712e94fede5284f50c066680edb356a808c027fa5d21fc22206010672a4fb792d4a4295876b6672b2541da8a36725761420c0c593cc1dcabbe57972d73a6b2743d616529204f49a11719a60c75bedab1bfad8a772d2f38e808135119902526d8087d81b425edd6e84033697f79b4b025864eab36d30bd0a376f882236e619a4b56d3b58c7e1dd585bc45e817610e1ff6bed6b50e653e2&p=c3759a42d4d059fe17f6c7710b59&user=baidu
// Disk Partition Table: PartRecord, PartSector, 64 bytes, in 0 sector
//******************************************
//http://cache.baidu.com/c?m=9d78d513d99712e94fece47d0d01d7170e25f4744dd7c7140fc3e54884142b564616f4cb2135660ec7823c390ef50f1aa8e737012a1e66ead993d95dddccc36979d430340740d1070f9504afc94422c324935cf4af19fabcf23893a9d8d2c8542490155a24&p=882a94479e8012a05fa6de2b135f&user=baidu
//**********************************************
//http://cache.baidu.com/c?m=9d78d513d99712e94fece47d0d01d7170e25f4744dd7c7140fc3e54884142b564616f4cb2135660ec7823c390ef50f1aa8e737012a1e66ead993d95dddccc36979d430340740d1070f9504afc94422c324935cf4af19fabcf23893a9d8d2c8542490155a24&p=882a94479e8012a05fa6de2b135f&user=baidu



#include "FAT.h"


//************************
//****data define
//************************
DWORD FirstDirClust;
DWORD FirstDirSector;
DWORD FirstDataSector;
DWORD FirstFATSector;

WORD FATsectors;			// #sectors for a FAT
WORD RootDirSectors;		// #sectors for a Root dir
WORD RootDirCount;			// the count of directory in Root dir

WORD BytesPerSector;
WORD SectorsPerClust;

BYTE FAT32_Enable;






// two pointers pointing to function, we dun use write in our program
BYTE (*FAT_ReadSector)(DWORD, BYTE *);
													//BYTE (*FAT_WriteSector)(DWORD, BYTE *);
// function pointer to SD card read and write single block
BYTE (*FAT_ReadSector)(DWORD sector, BYTE * buffer) = SD_ReadSingleBlock;
//BYTE (*FAT_WriteSector)(DWORD sector, BYTE * buffer) = SD_WriteSingleBlock;



//===========================
//===========================
void U512(unsigned char*buffer){
		unsigned int Ucnt;
		unsigned char ascii;
		unsigned char asciih;
		unsigned char asciil;
		for(Ucnt = 0; Ucnt<512; Ucnt++){
			ascii = buffer[Ucnt];
				asciih = ascii>>4;
				asciil = ascii<<4;
				asciil>>=4;

			while(!(UCSR0A&(1<<UDRE0)));
			if (asciih<0x0a)
				 UDR0 = (asciih + 0x30);			//123456789
			 else UDR0 = (asciih + 0x37);		//abcde

			while(!(UCSR0A&(1<<UDRE0)));
			 if (asciil<0x0a)
				 UDR0 = (asciil + 0x30);			//123456789
			 else UDR0 = (asciil + 0x37);		//abcde
		}
}

void U32(unsigned long read){
	unsigned long read32;
//	unsigned int read16;
//	unsigned int Ucnt;
	unsigned char ascii;
	unsigned char asciih;
	unsigned char asciil;

	read32 = read;
	ascii = read32>>24;
			asciih = ascii>>4;
			asciil = ascii<<4;
			asciil>>=4;

			while(!(UCSR0A&(1<<UDRE0)));
			if (asciih<0x0a)
				 UDR0 = (asciih + 0x30);			//123456789
			 else UDR0 = (asciih + 0x37);		//abcde

			while(!(UCSR0A&(1<<UDRE0)));
			 if (asciil<0x0a)
				 UDR0 = (asciil + 0x30);			//123456789
			 else UDR0 = (asciil + 0x37);		//abcde


				ascii = read32>>16;
						asciih = ascii>>4;
						asciil = ascii<<4;
						asciil>>=4;

						while(!(UCSR0A&(1<<UDRE0)));
						if (asciih<0x0a)
							 UDR0 = (asciih + 0x30);			//123456789
						 else UDR0 = (asciih + 0x37);		//abcde

						while(!(UCSR0A&(1<<UDRE0)));
						 if (asciil<0x0a)
							 UDR0 = (asciil + 0x30);			//123456789
						 else UDR0 = (asciil + 0x37);		//abcde


							ascii = read32>>8;
									asciih = ascii>>4;
									asciil = ascii<<4;
									asciil>>=4;

									while(!(UCSR0A&(1<<UDRE0)));
									if (asciih<0x0a)
										 UDR0 = (asciih + 0x30);			//123456789
									 else UDR0 = (asciih + 0x37);		//abcde

									while(!(UCSR0A&(1<<UDRE0)));
									 if (asciil<0x0a)
										 UDR0 = (asciil + 0x30);			//123456789
									 else UDR0 = (asciil + 0x37);		//abcde


											ascii = read32;
													asciih = ascii>>4;
													asciil = ascii<<4;
													asciil>>=4;

													while(!(UCSR0A&(1<<UDRE0)));
													if (asciih<0x0a)
														 UDR0 = (asciih + 0x30);			//123456789
													 else UDR0 = (asciih + 0x37);		//abcde

													while(!(UCSR0A&(1<<UDRE0)));
													 if (asciil<0x0a)
														 UDR0 = (asciil + 0x30);			//123456789
													 else UDR0 = (asciil + 0x37);		//abcde

}

//===========================
//===========================



struct FileInfoStruct FileInfo;			// file information to extract









//**************************
//****function define
//**************************


//----------------------------------------
//-----------FAT initialization-----------
//----------------------------------------

BYTE FAT_Init(void)
{
	// to save space, we can only read one in buffer and force data type to extract information blocks
	struct bootsector710	*bs = 0;		//boot sector
	struct bpb710			*bpb = 0;		//BIOS parameter
	struct partrecord		*pr = 0;		//record of partition

	BYTE buffer[512];
	WORD hidsec = 0;						//hidden sector

	DWORD Capacity;
	Capacity = SD_ReadCapacity();
	if(Capacity < 0xff) return 1;			//less than 512 byte or 1, failed to read capacity

	if(FAT_ReadSector(0, buffer)) return 1; // failed to read the BIOS sector
	bs = (struct bootsector710 *)buffer;	//bs = buffer =address of a struct bootsector

	if((bs->bsJump[0]!= 0xE9)&&(bs->bsJump[0]!=0xEB))
	{
		pr = (struct partrecord *)(((struct partsector *)buffer)->psPart); //extract partition sector
		hidsec = pr->prStartLBA;
		if(FAT_ReadSector(pr->prStartLBA, buffer))return 1;
		bs = (struct bootsector710 *)buffer;
	}
	if((bs->bsJump[0]!= 0xE9)&&(bs->bsJump[0]!=0xEB)){
		return 1;
	}
	//=========================================
	//=======this is for debugg
	//=========================================
	while(!(UCSR0A&(1<<UDRE0)));
	UDR0 = ' ';
	while(!(UCSR0A&(1<<UDRE0)));
	UDR0 = ' ';
	while(!(UCSR0A&(1<<UDRE0)));
	UDR0 = 'h';
	while(!(UCSR0A&(1<<UDRE0)));
	UDR0 = 'i';
	while(!(UCSR0A&(1<<UDRE0)));
	UDR0 = 'd';
	while(!(UCSR0A&(1<<UDRE0)));
	UDR0 = ':';
	U32(hidsec);
	while(!(UCSR0A&(1<<UDRE0)));
	UDR0 = '_';
	while(!(UCSR0A&(1<<UDRE0)));
	UDR0 = '_';
	U32(hidsec);

	//=========================================
	//=======this is for debugg
	//=========================================

	bpb = (struct bpb710 *)bs->bsBPB;								//extract BPB

	//----------------------check FAT type-------------------------
	if(bpb->bpbFATsecs)								//not zero, so not FAT32
	{
			FAT32_Enable = 0;						//support FAT16, our card is FAT16
			FATsectors = bpb->bpbFATsecs;			//#secs
			FirstDirClust = 2;

	}else{											//FAT32
			FAT32_Enable = 1;
			FATsectors = bpb->bpbBigFATsecs;
			FirstDirClust = bpb->bpbRootClust;
	}
	//---------------------find sector number of FAT and Dir-------

	BytesPerSector = bpb->bpbBytesPerSec;

	//=========================================
	//=======this is for debugg
	//=========================================
	while(!(UCSR0A&(1<<UDRE0)));
	UDR0 = '_';
	while(!(UCSR0A&(1<<UDRE0)));
	UDR0 = '_';
	while(!(UCSR0A&(1<<UDRE0)));
	UDR0 = 'B';
	while(!(UCSR0A&(1<<UDRE0)));
	UDR0 = 'P';
	while(!(UCSR0A&(1<<UDRE0)));
	UDR0 = 'S';
	while(!(UCSR0A&(1<<UDRE0)));
	UDR0 = ':';
	while(!(UCSR0A&(1<<UDRE0)));
	UDR0 = '_';
	while(!(UCSR0A&(1<<UDRE0)));
	UDR0 = '_';
	U32(BytesPerSector);
	//=========================================
	//=======this is for debugg
	//=========================================

	SectorsPerClust = (BYTE)bpb->bpbSecPerClust;	// ????word

	//=========================================
	//=======this is for debugg
	//=========================================
	while(!(UCSR0A&(1<<UDRE0)));
	UDR0 = '_';
	while(!(UCSR0A&(1<<UDRE0)));
	UDR0 = '_';
	while(!(UCSR0A&(1<<UDRE0)));
	UDR0 = 'S';
	while(!(UCSR0A&(1<<UDRE0)));
	UDR0 = 'P';
	while(!(UCSR0A&(1<<UDRE0)));
	UDR0 = 'C';
	while(!(UCSR0A&(1<<UDRE0)));
	UDR0 = ':';
	while(!(UCSR0A&(1<<UDRE0)));
	UDR0 = '_';
	while(!(UCSR0A&(1<<UDRE0)));
	UDR0 = '_';
	U32(SectorsPerClust);
	//=========================================
	//=======this is for debugg
	//=========================================


	FirstFATSector = bpb->bpbResSectors + hidsec;	//LAB of FAT 1st sector

	//=========================================
	//=======this is for debugg
	//=========================================
	while(!(UCSR0A&(1<<UDRE0)));
	UDR0 = '_';
	while(!(UCSR0A&(1<<UDRE0)));
	UDR0 = '_';
	while(!(UCSR0A&(1<<UDRE0)));
	UDR0 = '1';
	while(!(UCSR0A&(1<<UDRE0)));
	UDR0 = 'F';
	while(!(UCSR0A&(1<<UDRE0)));
	UDR0 = 'S';
	while(!(UCSR0A&(1<<UDRE0)));
	UDR0 = ':';
	while(!(UCSR0A&(1<<UDRE0)));
	UDR0 = '_';
	while(!(UCSR0A&(1<<UDRE0)));
	UDR0 = '_';
	U32(FirstFATSector);
	//=========================================
	//=======this is for debugg
	//=========================================



	RootDirCount = bpb->bpbRootDirEnts;				//if FAT32, 0

	//=========================================
	//=======this is for debugg
	//=========================================
	while(!(UCSR0A&(1<<UDRE0)));
	UDR0 = '_';
	while(!(UCSR0A&(1<<UDRE0)));
	UDR0 = '_';
	while(!(UCSR0A&(1<<UDRE0)));
	UDR0 = 'R';
	while(!(UCSR0A&(1<<UDRE0)));
	UDR0 = 'D';
	while(!(UCSR0A&(1<<UDRE0)));
	UDR0 = 'C';
	while(!(UCSR0A&(1<<UDRE0)));
	UDR0 = ':';
	while(!(UCSR0A&(1<<UDRE0)));
	UDR0 = '_';
	while(!(UCSR0A&(1<<UDRE0)));
	UDR0 = '_';
	U32(RootDirCount);
	//=========================================
	//=======this is for debugg
	//=========================================

	RootDirSectors = (RootDirCount*32)>>9;		// 32 bytes/Dir ??? little problem here
	//=========================================
	//=======this is for debugg
	//=========================================
	while(!(UCSR0A&(1<<UDRE0)));
	UDR0 = '_';
	while(!(UCSR0A&(1<<UDRE0)));
	UDR0 = '_';
	while(!(UCSR0A&(1<<UDRE0)));
	UDR0 = 'R';
	while(!(UCSR0A&(1<<UDRE0)));
	UDR0 = 'D';
	while(!(UCSR0A&(1<<UDRE0)));
	UDR0 = 'S';
	while(!(UCSR0A&(1<<UDRE0)));
	UDR0 = ':';
	while(!(UCSR0A&(1<<UDRE0)));
	UDR0 = '_';
	while(!(UCSR0A&(1<<UDRE0)));
	UDR0 = '_';
	U32(RootDirSectors);
	//=========================================
	//=======this is for debugg
	//=========================================

	FirstDirSector = FirstFATSector + bpb->bpbFATs*FATsectors;		//for FAT32
	//=========================================
	//=======this is for debugg
	//=========================================
	while(!(UCSR0A&(1<<UDRE0)));
	UDR0 = '_';
	while(!(UCSR0A&(1<<UDRE0)));
	UDR0 = '_';
	while(!(UCSR0A&(1<<UDRE0)));
	UDR0 = '1';
	while(!(UCSR0A&(1<<UDRE0)));
	UDR0 = 'D';
	while(!(UCSR0A&(1<<UDRE0)));
	UDR0 = 'S';
	while(!(UCSR0A&(1<<UDRE0)));
	UDR0 = ':';
	while(!(UCSR0A&(1<<UDRE0)));
	UDR0 = '_';
	while(!(UCSR0A&(1<<UDRE0)));
	UDR0 = '_';
	U32(FirstDirSector);
	//=========================================
	//=======this is for debugg
	//=========================================


	FirstDataSector = FirstDirSector + RootDirSectors;				//for FAT16
	//=========================================
	//=======this is for debugg
	//=========================================
	while(!(UCSR0A&(1<<UDRE0)));
	UDR0 = '_';
	while(!(UCSR0A&(1<<UDRE0)));
	UDR0 = '_';
	while(!(UCSR0A&(1<<UDRE0)));
	UDR0 = '1';
	while(!(UCSR0A&(1<<UDRE0)));
	UDR0 = 'D';
	while(!(UCSR0A&(1<<UDRE0)));
	UDR0 = 'S';
	while(!(UCSR0A&(1<<UDRE0)));
	UDR0 = ':';
	while(!(UCSR0A&(1<<UDRE0)));
	UDR0 = '_';
	while(!(UCSR0A&(1<<UDRE0)));
	UDR0 = '_';
	U32(FirstDataSector);
	//=========================================
	//=======this is for debugg
	//=========================================
	//FirstDirSector for FAT16 is the start of root directory
	//FirstDataSector for FAT16 is the start of DATA
	//FirstDataSector for FAT32 is the start of DATA, is the first directory, since FAT32 has no root dir

//	while(1);
	return 0;
}




//--------------------------------------------------------------------
//-----------read a sector from cluster, address part, to buffer------
//--------------------------------------------------------------------

BYTE FAT_LoadPartCluster(DWORD cluster, unsigned part, BYTE *buffer)
{
		DWORD sector;
		// DATA region started from cluster 2 // 0, 1 Cluster reserved
		sector = FirstDataSector + ((DWORD)(cluster-0x0002))*((DWORD)SectorsPerClust);

		//=============================
		// for debug , output to monitor
		//=============================
/*
		while(!(UCSR0A&(1<<UDRE0)));
		UDR0 = ' ';
		while(!(UCSR0A&(1<<UDRE0)));
		UDR0 = ' ';
		while(!(UCSR0A&(1<<UDRE0)));
		UDR0 = 'S';
		while(!(UCSR0A&(1<<UDRE0)));
		UDR0 = 't';
		while(!(UCSR0A&(1<<UDRE0)));
		UDR0 = 'S';
		while(!(UCSR0A&(1<<UDRE0)));
		UDR0 = 'E';
		while(!(UCSR0A&(1<<UDRE0)));
		UDR0 = 'C';
		while(!(UCSR0A&(1<<UDRE0)));
		UDR0 = ':';
		while(!(UCSR0A&(1<<UDRE0)));
		UDR0 = ' ';
		U32(sector);
*/

		sector+=part;
		if(FAT_ReadSector(sector, buffer)){
			return 1;
		}
		else {
/*			while(!(UCSR0A&(1<<UDRE0)));
			UDR0 = '-';
			while(!(UCSR0A&(1<<UDRE0)));
			UDR0 = '>';
			U32(sector);
*/			return 0;
		}
}



//-------------------------------------------------------------------------------------------------
//-----------return the sector number of next cluster in FAT,--------------------------------------
//fail to return bad clust 0x0ffffff7
//-------------------------------------------------------------------------------------------------
DWORD FAT_NextCluster(DWORD cluster)
{
	BYTE buffer[512];
	DWORD sector;
	DWORD offset;

	if(FAT32_Enable)offset = cluster/128;			// large FAT32
		else offset = cluster/256;							// for FAT16
	if(cluster<2) return 0x0ffffff8;							//0,1 cluster reserved

	sector = FirstFATSector + offset;
	if(FAT_ReadSector(sector,buffer))return 0x0ffffff8;			//failed to read FAT

	if(FAT32_Enable){
		offset = cluster%128;
		sector = ((DWORD *)buffer)[offset];
	}else{
		offset = cluster%256;
		sector = ((WORD *)buffer)[offset];
	}
	return (DWORD)sector;
}



//--------------------------------------------------------
//----------open a directory with the given path----------
//--------------------------------------------------------
DWORD FAT_OpenDir(BYTE *dir)							//we allow only depth 0 in our project for simpleness
{
	BYTE *p=dir;
//	BYTE deep = 1;
//	BYTE i,j;
//	BYTE name[11];

	DWORD cluster =0;									//FAT16 root dir
	if(FAT32_Enable)
	{		cluster = FirstDirClust;						//FAT32 no root dir

	}

	if(*p!='\\')return 1;								//valid path start from '//'
/*	for(j=0;j<11;j++)name[j]=0x20;
	j=0;p++;
	while(*p)// string will end with '\0'
	{
		if(*p>='a' && *p<='z')name[j]=(*p++)-0x20;
		else name[j]=*p++;
		j++;
	}
	if(j == 0)return cluster;
	if(FAT_FindItem(cluster,name, &FileInfo))return 1;	//failed find the dir
	cluster = FileInfo.StartCluster;
*/
	return cluster;
}

//--------------------------------------------------------
//----------copy item of one direntry---------------------
//--------------------------------------------------------
void CopyDirentryItem(struct direntry *Desti, struct direntry *Source)
{
	BYTE i;
	for(i=0;i<8;i++)Desti->deName[i] = Source->deName[i];
	for(i=0;i<3;i++)Desti->deExtension[i] = Source->deExtension[i];
	Desti->deAttributes = Source->deAttributes;
	Desti->deLowerCase = Source->deLowerCase;
	Desti->deCHundredth = Source->deCHundredth;
	for(i=0;i<2;i++)Desti->deCTime[i] = Source->deCTime[i];
	for(i=0;i<2;i++)Desti->deCDate[i] = Source->deCDate[i];
	for(i=0;i<2;i++)Desti->deADate[i] = Source->deADate[i];
	Desti->deHighClust = Source->deHighClust;
	for(i=0;i<2;i++)Desti->deMTime[i] = Source->deMTime[i];
	for(i=0;i<2;i++)Desti->deMDate[i] = Source->deMDate[i];
	Desti->deStartCluster = Source->deStartCluster;
	Desti->deFileSize = Source->deFileSize;

}
//---------------------------------------------------------------------------
//-----------search the file, according to count-----------------------------
// if *count = 0, num_songs, if *count != 0, *MusicInfo for file information-
//---------------------------------------------------------------------------
BYTE search(BYTE *dir, struct direntry *MusicInfo, BYTE *count, BYTE *type)
{
	BYTE *buffer;
	DWORD sector;
	DWORD cluster;
	DWORD tempclust;
	BYTE cnt;
	WORD offset;
	BYTE i = 0;
	struct direntry *item = 0;

	cluster = FAT_OpenDir(dir);
	if(cluster == 1){
		return 1;							//invalid,reserveed cluster
	}

	if(cluster == 0 && FAT32_Enable == 0)				//valid root dir
	{


		buffer = malloc(512);if(buffer == 0)return 1;	//fail to get buffer, return 1
		for(cnt=0;cnt<RootDirSectors;cnt++)
		{
			if(FAT_ReadSector(FirstDirSector + cnt,buffer)){free(buffer);return 1;}

			for(offset = 32;offset<512;offset+=32)
			{
				item = (struct direntry *)(&buffer[offset]);
				if((item->deName[0]!='.') & (item->deName[0] != 0x00) & (item->deName[0] != 0xe5) & (item->deAttributes != 0x0f))
				{	// we only support MP3 file type, with 1, maybe future extension to midi, wma, wav
					CopyDirentryItem(MusicInfo,item);
					*type = 1; i++;
					if(i==*count){free(buffer);return 0;}	//find song count

				}//end if can find a valid name
			}//end of search one sector
		}//end of search the root dir
		free(buffer);
	}//end of cluster 0
	else												// not root dir
	{
		tempclust = cluster;
		while(1)
		{
			sector = FirstDataSector +(DWORD)(tempclust-2)*(DWORD)SectorsPerClust;
			buffer = malloc(512);if(buffer==0){
				return 1;
			}


			for(cnt=0;cnt<SectorsPerClust;cnt++)
			{
				if(FAT_ReadSector(sector+cnt,buffer)){free(buffer);return 1;}

				for(offset=32;offset<512;offset+=32)
				{
					item = (struct direntry *)(&buffer[offset]);
					if((item->deName[0] != '.') & (item->deName[0] != 0x00) & (item->deName[0] != 0xe5) & (item->deAttributes != 0x0f))
					{
						CopyDirentryItem(MusicInfo,item);
						*type = 1; i++;
						if(i==*count){free(buffer);return 0;}
					}//end of find one valid name
				}//end of one sector
			}//end of one clust
			free(buffer);//release
			tempclust=FAT_NextCluster(tempclust);//next cluster
			if(tempclust == 0x0fffffff || tempclust == 0x0ffffff8 || (FAT32_Enable == 0 && tempclust == 0xffff))break;
		}//end of while(1)
	}//end of cluster non-0
	if(*count==0) *count = i;							//return last song
	return 0;
}



//----------find a item in the dir with its name , not used
//----------return the starting cluster number
//----------not used in our prgram, as no search by file name
/*
DWORD FAT_FindItem(DWORD cluster, BYTE *name, struct FileInfoStruct *FileInfo)
{
	BYTE *buffer;
	DWORD tempclust;
	DWORD sector;
	BYTE cnt;
	WORD offset;
	BYTE i;
	struct direntry *item = 0;

	if((cluster == 0)&&(FAT32_Enable == 0))				//FAT16, root dir in 0 cluster
	{
		buffer = malloc(512); if(buffer == 0)return 1;
		for(cnt = 0; cnt<RootDirSectors; cnt++)
		{
			if(FAT_ReadSector(FirstDirSector+cnt,buffer)){free(buffer);return 1;}
			for(offset = 0; offset<512; offset+=32)
			{	//32 bytes per entry
				item = (struct direntry *)(&buffer[offset]);
				if((item->deName[0]!=0x00)&(item->deName[0]!=0xe5)&(item->deAttributes!=0x0f))
				{	//this dir not empty, not long name
					for(i=0;i<11;i++){
						if(buffer[offset+i]!=name[i])break;	//check name
					}
					if(i==11){
						FileInfo->StartCluster = item->deStartCluster + (((DWORD)item->deHighCluster)<<16);
						FileInfo->Size = item->deFileSize;
						FileInfo->Attr = item->deAttributes;
						FileInfo->Sector = FirstDirSector + cnt;
						FileInfo->Offset = offset;
						free(buffer);return 0;
					}//end of read one entry
				}//end if not empty dir
			}//end search direntry in one sector, 32 bytes per offset step
		}//end search one sector, cnt<rootdirsecs sector
		free(buffer);
	}//end if root dir

	else												//not root dir, not 0 clust
	{
		tempclust = cluster;
		while(1){
			sector = FirstDataSector + (DWORD)(tempclust-2)*(DWORD)SectorsPerClust;
			buffer = malloc(512); if(buffer==0)return 1;
			for(cnt = 0; cnt<SectorsPerClust; cnt++){
				if(FAT_ReadSector(sector+cnt,buffer)){free(buffer);return 1;}
				for(offset = 0; offset<512; offset+=32){

					item = (struct direntry *)(&buffer[offset]);
					if((item->deName[0]!=0x00)&(item->deName[0]!=0xe5)&(item->deAttributes!=0x0f))
					{	//this dir not empty, not long name
						for(i=0;i<11;i++){
							if(buffer[offset+i]!=name[i])break;	//check name
						}
						if(i==11){
							FileInfo->StartCluster = item->deStartCluster + (((DWORD)item->deHighCluster)<<16);
							FileInfo->Size = item->deFileSize;
							FileInfo->Attr = item->deAttributes;
							FileInfo->Sector = FirstDirSector + cnt;
							FileInfo->Offset = offset;
							free(buffer);return 0;
						}//end of read one entry
					}//end if not empty direntry
				}//end search one sector
			}//end search oen clust
			free(buffer);
			tempclust = FAT_NextCluster(tempclust);
			if((tempclust == 0x0fffffff)||(tempclust == 0x0ffffff8)||(FAT32_Enable == 0 && tempclust == 0xffff))break;	//invalid cluster
		}//end While
	}//end if not root dir
	return 1;											// failed to find the item
}
*/
